﻿using System;
using System.IO;
using System.Text;
using LegoBotPrimaAbstractions;
using LegoBotPrimaAbstractions.Extensions;

namespace LegoBotPrima
{
    public class WorkflowLogger : IWorkflowLogger
    {
        private readonly StreamWriter _writer;

        public WorkflowLogger()
        {
            if (Config.Instance.LogCallToWorkflow)
            {
                if (File.Exists(Config.Instance.LogPath))
                {
                    File.Delete(Config.Instance.LogPath);
                }
                _writer = new StreamWriter(Config.Instance.LogPath, true);
            }
        }

        public void LogMethodCall(string method, params object[] args)
        {
            if (Config.Instance.LogCallToWorkflow)
            {
                _writer.Write(FormatMethodCall(method, args));
                _writer.Flush();
            }
                
        }
        public void LogKeyState(string name, object data)
        {
            if (Config.Instance.LogCallToWorkflow)
            {
                _writer.Write(FormatKeyState(name, data));
                _writer.Flush();
            }
        }

        public void Call(Action<IWorkflowLogger> func)
        {
            if (Config.Instance.LogCallToWorkflow)
            {
                func(this);
                _writer.Flush();
            }
        }

        private static string FormatKeyState(string name, object data)
        {
            var sb = new StringBuilder();
            sb.Append("/* ");
            sb.Append(name);
            sb.Append(": ");
            sb.Append(data ?? "null");
            sb.Append(" */");
            sb.AppendLine();
            return sb.ToString();
        }

        private static string FormatMethodCall(string method, params object[] args)
        {
            var sb = new StringBuilder();
            sb.Append("workflow.");
            sb.Append(method);
            sb.Append("(");
            var isFirst = true;
            foreach (var obj in args)
            {
                if (isFirst) isFirst = false;
                else sb.Append(", ");

                var str = (obj != null && obj is string)
                            ? "\"" + obj.ToString().Replace("\"", "\\\"") + "\""
                            : (obj is Boolean) 
                                ? obj.ToString().ToLower() 
                                : (obj is DateTime) 
                                    ? ((DateTime) obj).AsInitCall()
                                    : (obj ?? "null").ToString();

                sb.Append(str);
            }
            sb.Append(");");
            sb.AppendLine();
            return sb.ToString();
        }

        public void Dispose()
        {
            _writer.Close();
            _writer.Dispose();
        }
    }
}
